#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：    logs.py
   Author :       zyq
   CreateDate：   2024/7/12 16:32
   Remark :  优化后的日志类工具
-------------------------------------------------
"""

"""
日志的四大操作: 
记录器（Logger）：用于记录日志的信息，相当于记录员root手中的笔
处理器（Handler）：用于指定日志记录的载体。（控制台，本地磁盘文件）
格式器（Formatter）：用于指定日志的书写格式。写字的布局排版
过滤器（Filter）：用于过滤指定的有用的日志信息（不常用）
"""

import os
import logging

from guitesting.common.util import log_process
from guitesting.common.file.operation_yaml import ReadYaml

log_conf: dict = ReadYaml().get_every_config("LOG_CONFIG")

# 实例化日志记录器（收集器）
logger = logging.getLogger(name="Log")
# 定义输出级别
logger.setLevel(log_conf.get("LOG_LEVEL"))


def set_handler(levels):
    """
    设置日志处理器。

    Args:
        levels (str): 日志级别，可选值为'error'或其他值。
            如果为'error'，则添加针对错误的日志处理器。
            否则，添加默认的日志处理器。

    Returns:
        None: 该函数没有返回值，只是为日志对象添加了相应的处理器。

    """
    if levels == 'error':  # 判断如果是error就添加error的handler
        logger.addHandler(Log.error_handle)
    else:  # 其他添加到infohandler
        logger.addHandler(Log.handler)
    logger.addHandler(Log.ch)  # 全部输出到console


def remove_handler(levels):
    """
    从日志记录器中移除指定级别的处理器或默认的处理器。

    Args:
        levels (str): 日志级别，用于指定要移除的处理器。
            如果为'error'，则移除错误级别的处理器；
            否则，移除默认的处理器。

    Returns:
        None: 此函数不返回任何值，只是修改日志记录器的处理器设置。

    """
    if levels == 'error':
        logger.removeHandler(Log.error_handle)
    else:
        logger.removeHandler(Log.handler)
    logger.removeHandler(Log.ch)


class Log:
    __obj = None

    @staticmethod
    def __new__(cls, *args, **kwargs):
        """
        单例模式的静态方法，用于创建类的实例。

        Args:
            *args: 可变位置参数，用于传递给父类的__new__方法。
            **kwargs: 可变关键字参数，用于传递给父类的__new__方法。

        Returns:
            cls的__obj属性所引用的实例，即单例对象。

        """
        # 如果类的__obj属性不存在
        if not cls.__obj:
            # 调用父类的__new__方法创建一个新的实例，并将其赋值给类的__obj属性
            cls.__obj = super().__new__(cls)
        # 返回类的__obj属性
        return cls.__obj

    # 实例化文件管理类
    log_process = log_process.LogProcess()
    # 调用创建文件, 传参确认文字日志
    log_dir = log_process.get_log_dir()
    # 指定输出文件, log_dir[0]是日志路径，1是图片路径
    log_file = os.path.join(log_dir[0], 'logs.log')
    # 设置日志输出格式，从配置文件中获取
    formatter = logging.Formatter(fmt=log_conf.get("FORMATTER"))

    # 指定输出渠道
    # 1、控制台输出
    ch = logging.StreamHandler()  # 实例化处理器
    ch.setLevel(log_conf.get("LOG_LEVEL_CONSOLE"))  # 设置日志级别
    ch.setFormatter(formatter)  # 设置日志格式
    # 2、INFO日志输出
    handler = logging.FileHandler(filename=log_file, encoding='utf-8')
    handler.setLevel('INFO')
    handler.setFormatter(formatter)
    # 3、错误日志输出
    error_handle = logging.FileHandler(filename=log_file, encoding='utf-8')
    error_handle.setLevel('ERROR')
    error_handle.setFormatter(formatter)

    @staticmethod
    def debug(msg):
        """
        以debug级别输出日志信息。

        Args:
            msg (str): 要输出的日志信息。

        Returns:
            None: 此函数无返回值，仅用于输出日志信息。

        """
        # 设置日志处理器为debug级别
        set_handler('debug')
        # 输出debug级别的日志信息
        logger.debug(msg)
        # 移除debug级别的日志处理器
        remove_handler('debug')

    @staticmethod
    def info(msg):
        """
        记录一条info级别的日志。

        Args:
            msg (str): 要记录的日志信息。

        Returns:
            None: 该函数没有返回值，仅用于记录日志。

        """
        # 设置日志处理器为'info'
        set_handler('info')
        # 记录info级别的日志
        logger.info(msg)
        # 移除'info'日志处理器
        remove_handler('info')

    @staticmethod
    def error(msg):
        """
        记录错误日志并输出异常信息。

        Args:
            msg (str): 错误信息。

        Returns:
            None: 此方法没有返回值。

        """
        # 设置错误日志处理器
        set_handler('error')
        # 同时输出异常信息
        logger.error(msg, exc_info=True)
        # 移除错误日志处理器
        remove_handler('error')


if __name__ == '__main__':
    Log.debug('this is a debug message')
    Log.info('this is an info message')
